use std::ops::Add;

//所有的原型类都必须有一个通用的接口， 使得即使在对象所属的具体类未知的情况下也能复制对象。
//原型对象可以生成自身的完整副本， 因为相同类的对象可以相互访问对方的私有成员变量。
trait Inode {
    fn print(&self, rec: String);
    fn clone_s(&self) -> Box<dyn Inode>;
}

struct File {
    name: String,
}

struct Folder {
    name: String,
    children: Vec<Box<dyn Inode>>,
}

impl Inode for File {
    fn print(&self, rec: String) {
        print!("{} {}", rec, self.name);
    }

    fn clone_s(&self) -> Box<dyn Inode> {
        Box::new(File { name: self.name.to_string().add("_clone") })
    }
}

impl Inode for Folder {
    fn print(&self, rec: String) {
        print!("{} {}", rec, self.name);
    }
    fn clone_s(&self) -> Box<dyn Inode> {
        let mut folder = Folder { name: self.name.to_string().add("_clone"), children: vec![] };
        let mut result = Vec::new();
        for x in self.children.iter() {
            result.push(x.clone_s());
        };
        folder.children = result;
        Box::new(folder)
    }
}

#[test]
fn main() {
    let folder = Folder {
        name: String::from("A"),
        children: vec![
            Box::new(Folder {
                name: String::from("b"),
                children: vec![],
            }), Box::new(File {
                name: String::from("c"),
            }),
        ],
    };
    println!("{:?}", folder.name);
    println!("{:?}", folder.children.len());
    let new_folder: Box<dyn Inode> = folder.clone_s();
    new_folder.print(String::from(""));
}
